package com.o2o.sphinx;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.annotation.Resource;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import com.o2o.base.BaseRepository;
import com.o2o.model.topic.Topic;
import com.o2o.repository.TopicRepository;

@Scope("prototype")
@Service
public class SphinxSearch extends BaseRepository{
	private static Properties prop = new Properties();
	private static String host;
	private static int port;
	private static int timeout = 20;// 默认为5S
	private static SphinxClient cl = null;
	
	private static int mode = SphinxClient.SPH_MATCH_EXTENDED;
	private String index = "*"; // 默认为所有
	private static int sortMode = SphinxClient.SPH_SORT_EXPR;

	private String groupSort = "@group desc";
	
	@Resource
	TopicRepository topicRepository;
	
	static {
		InputStream is = SphinxSearch.class.getResourceAsStream("config.properties");
		try {
			// 加载配置文件
			prop.load(is);
			host = prop.getProperty("host").trim();
			port = Integer.parseInt(prop.getProperty("port").trim());
			timeout = Integer.parseInt(prop.getProperty("timeout").trim());
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			System.out.println("读取sphinx配置文件错误");
			e.printStackTrace();
		}
	}

	public static SphinxClient getSphinxClient() {
//		synchronized (cl) {
			if(cl == null){
				cl = new SphinxClient();
				try {
					cl.SetServer(host, port);
					cl.SetWeights(new int[] { 10, 1 });
					cl.SetConnectTimeout(timeout);
				} catch (SphinxException e) {
					e.printStackTrace();
				}
			}
//		}
		return cl;
	}

	public List<Topic> getSearchResult(int sort,String sortName,String keyword, int page, int size,int number,int productType) throws Exception {
		List<SphinxMatch> list= new ArrayList<SphinxMatch>();
		SphinxClient cl = getSphinxClient();
		cl.SetMatchMode(mode);
		SortUtil.getSphinx(cl, sort, sortName);
		cl.SetRetries(2);
		if((page-1)*size < 1000) //默认会返回1000条记录
			cl.SetLimits((page-1)*size, size+1);
		cl.ResetFilters();//重置
		//设置权重
		Map<String, Integer> fieldWeights = Collections.synchronizedMap(new HashMap<String, Integer>()); // 权重设置
		fieldWeights.put("topicTitle", 8); //设置权重
		fieldWeights.put("topicString", 4);
		if(fieldWeights != null &&fieldWeights.size() > 0)
			cl.SetFieldWeights(fieldWeights);
		String num = ""+productType+number;
		int stopKey = 0;//处理后的between ?,?
		int i = num.length()-1;
		while(i>=0){
			char tmp = num.charAt(i);
			char c1 = '0';
			if(c1 !=tmp){
				String afterNumber = num.substring(0, i+1);
				int stop = Integer.parseInt(afterNumber);
				String finalS = (stop+1)+""+num.substring(i+1, num.length());
				stopKey = Integer.parseInt(finalS);
				break;
			}
			i--;
		}
		cl.SetFilterRange("category_number", number, stopKey, false);
//		if(param != null && !param.isEmpty()){
//			Set<Entry<String,Integer>> entrySet = param.entrySet();
//			for (Entry<String, Integer> entry : entrySet) {	//设置条件筛选
//				cl.SetFilter(entry.getKey(), entry.getValue(), false);
//			}
//		}
//		if (groupSortName != null && groupSortName.length() > 0){
//			cl.SetGroupBy(groupSortName, SphinxClient.SPH_GROUPBY_ATTR, groupSort);
//			cl.SetGroupDistinct("");
//		}
		long a = System.currentTimeMillis();
		SphinxResult res = cl.Query(keyword, index);
		long b = System.currentTimeMillis();
		logger.info("Sphinx Search time:"+(b-a)+"ms");
		if (res == null) {
			logger.error("sphinx search result empty&&Error: " + cl.GetLastError()); //出错
			return null;
		}	
		if (cl.GetLastWarning() != null && cl.GetLastWarning().length() > 0)
			System.out.println("WARNING: " + cl.GetLastWarning() + "\n");
		String[] topicIds = new String[size+1];
		for (i = 0; i < res.matches.length; i++) {
			SphinxMatch info = res.matches[i];
			topicIds[i] = info.docId+"";
		}
		b = System.currentTimeMillis();
		List<Topic> topics = topicRepository.getTopicProductListByTopicIds(topicIds);
		a = System.currentTimeMillis();
		logger.info("topicService query topics by ids time:"+(a-b)+"ms");
		Map<Long,Topic> map = Collections.synchronizedMap(new HashMap<Long,Topic>());
		for (Topic topic : topics) {
			map.put(topic.getId(), topic);
		}
		List<Topic> sortTopics = new ArrayList<Topic>();
		for(i =0;i<topics.size();i++){
			long id = Long.parseLong(topicIds[i]);
			Topic topic = map.get(id);
			sortTopics.add(topic);
		}
		return sortTopics;
		}
}
